package de.au.fi.manager;

import java.util.Arrays;
import java.util.List;

import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;

import org.ektorp.CouchDbConnector;
import org.ektorp.ViewQuery;
import org.ektorp.support.CouchDbRepositorySupport;
import org.ektorp.support.GenerateView;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import de.au.fi.domain.Stock;
import de.au.fi.domain.EntityHelper;

public class GenericManager<T> extends CouchDbRepositorySupport<T> {

	Logger log = LoggerFactory.getLogger(this.getClass());
	
	Class<T> type;

	public GenericManager(CouchDbConnector db, Class<T> type) {
		super(type, db);
		this.type = type;
		initStandardDesignDocument();
	}
	
	public List<T> saveEntities(T... objects) {
		for(Object object : objects)
			save(object);
		return Arrays.asList(objects);
	}
	
	public List<T> saveEntities(List<T> objects) {
		for(Object object : objects)
			save(object);
		return (List<T>) Arrays.asList(objects);
	}

	public <T> T save(T object) {
		String id = null;
		try {
			id = EntityHelper.getIdForObject(object);
			if (id == null) {
				try {
					FacesContext.getCurrentInstance().addMessage(null,
							new FacesMessage("no id given cannot save"));
				} catch (Exception e) {
					log.error("Could not write faces msg, probably test.");
				}
				return (T) object;
			}
			if (contains(id)) {
			T oldStock = (T) get(id);
			object = EntityHelper.synchronizeObjects(object, oldStock);
			db.update(object);
			} else
				db.create(object);
		} catch (Exception e) {
			log.error("Error saving stock {}", id, e);
		}
		return (T) get(id);
	}

	@GenerateView @Override
	public List<T> getAll() {
		ViewQuery q = createQuery("all")
						.descending(true)
						.includeDocs(true);
		return db.queryView(q, type);
	}
}
